package cn.hinglo.common.plugin.mongodb;

import com.jfinal.kit.StrKit;
import com.mongodb.MongoClientSettings;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import org.bson.Document;
import org.bson.codecs.configuration.CodecRegistries;
import org.bson.codecs.configuration.CodecRegistry;
import org.bson.codecs.pojo.PojoCodecProvider;

import java.util.List;

/**
 * @createTime: 2019/1/11
 * @author: HingLo
 * @description: 工具
 */
public class MongoDbKit {

    /***
     * mongodb的链接客服端,
     */
    private static MongoClient client;

    /**
     * 默认数据库的名称
     */
    private static String database;
    /***
     * pojo codecRegistry
     */
    private static CodecRegistry pojoCodecRegistry;
    /***
     * 默认的数据库对象,线程安全对象
     */
    private static MongoDatabase mongoDatabase;

    static void init(MongoClient client, String database) {
        pojoCodecRegistry = CodecRegistries.fromRegistries(MongoClientSettings.getDefaultCodecRegistry(),
                CodecRegistries.fromProviders(PojoCodecProvider.builder().automatic(true).build()));
        MongoDbKit.database = database;
        MongoDbKit.client = client;
        MongoDbKit.mongoDatabase = client.getDatabase(database);
    }

    /***
     * 通过集合名称获取集合信息
     * @param collectionName 集合名称
     * @return 返回对象
     */
    public static MongoCollection<Document> use(String collectionName) {
        return use(database, collectionName);
    }

    public static <T> MongoCollection<T> use(String collectionName, Class<T> t) {
        return use(database, collectionName, t);
    }

    private static MongoCollection<Document> use(String database, String collectionName) {
        if (StrKit.notBlank(database, collectionName)) {
            return database.equals(MongoDbKit.database) ? mongoDatabase.getCollection(collectionName) : client.getDatabase(database).getCollection(collectionName);
        }
        throw new RuntimeException("默认数据库或者集合不能为空");
    }

    private static <T> MongoCollection<T> use(String database, String collectionName, Class<T> t) {
        if (StrKit.notBlank(database, collectionName)) {
            return database.equals(MongoDbKit.database) ? mongoDatabase.withCodecRegistry(pojoCodecRegistry).getCollection(collectionName, t) : client.getDatabase(database).withCodecRegistry(pojoCodecRegistry).getCollection(collectionName, t);
        }
        throw new RuntimeException("默认数据库或者集合不能为空");
    }

    /***
     * 获取默认的数据库
     * @return 数据库
     */
    public static MongoDatabase getDb() {
        return client.getDatabase(database);
    }

    /***
     * 根据实体Bean来进行插入操作
     * @param collectionName 集合名称
     * @param document 具体实体bean
     * @param <T> 泛型实体bean
     */
    public static <T> void insertOne(String collectionName, T document) {
        insertOne(database, collectionName, document);
    }

    /***
     * 根据实体Bean来进行插入操作
     * @param collectionName 集合名称
     * @param document 具体实体bean
     * @param <T> 泛型实体bean
     */
    public static <T> void insertOne(String database, String collectionName, T document) {
        if (document != null) {
            if (document instanceof Document) {
                use(database, collectionName).insertOne((Document) document);
            } else {
                use(database, collectionName, (Class<T>) document.getClass()).insertOne(document);
            }
        }
    }


    /***
     * 根据实体Bean来进行插入操作
     * @param collectionName 集合名称
     * @param document 具体实体bean
     * @param <T> 泛型实体bean
     */
    public static <T> void insertMany(String collectionName, List<T> document) {
        insertMany(database, collectionName, document);
    }

    /***
     * 根据实体Bean来进行插入操作
     * @param collectionName 集合名称
     * @param document 具体实体bean
     * @param <T> 泛型实体bean
     */
    public static <T> void insertMany(String database, String collectionName, List<T> document) {
        if (!document.isEmpty()) {
            if (document.get(0) instanceof Document) {
                use(database, collectionName).insertMany((List<Document>) document);
            } else {
                use(database, collectionName, (Class<T>) document.get(0).getClass()).insertMany(document);
            }
        }
    }
}
